/**
 * Package containing the global PluginInterface that all plugin components must implement, the PluginContainerInterface
 * that all plugin containers are required to implement, plus interface(s) specific to the
 * top-level admin desktop area.
 */
jsx3.lang.Package.definePackage("ux.megatron.plugin", function(plugin) {
});

/**
 * The base plugin interface that all plugin components are REQUIRED to implement.
 */
jsx3.lang.Class.defineInterface(
        "ux.megatron.plugin.PluginInterface",
        null,
        function(plugin) {

            plugin.prototype.isEditMode = false;

            /**
             * Method to be implemented by all plugin components.<br /><br />
             * Should perform any initialization of the class that will be done just after instantiation.  This is
             * pre-implemented to do nothing, and thus only needs to be implemented by the plugin component if
             * special initialization is needed.
             */
            plugin.prototype.initPlugin = function() {
            }

            /**
             * Abstract method to be implemented by all plugin components<br /><br />
             * Must return the namespace for the plugin to which it belongs.  Used for resolving URIs.
             *
             * @return {String} the namespae of the plugin to which this plugin component belongs
             */
            plugin.prototype.getNamespace = jsx3.lang.Method.newAbstract();

            plugin.prototype.getUIResources = function() {
            }

            if(!plugin.prototype.destroyPlugin) {
                /**
                 * Abstract method to be implemented by all plugin components.<br /><br />
                 * Should do any cleanup (unsubscribing, variable deletion, etc.) before the component instance is
                 * destroyed.
                 */
                plugin.prototype.destroyPlugin = function() {
                    if(this.isPluginContainer()) {
                        this.destroyPlugin = ux.megatron.plugin.PluginContainerInterface.prototype.destroyPlugin;
                        this.destroyPlugin();
                    }
                }
            }

            /**
             * Abstract method to be implemented by all plugin components.<br /><br />
             * Called by the parent plugin container to allow the plugin component to load it's content into a
             * particular extension point's content area.<br /><br />
             * Parent plugin containers should call this when it is the proper time for a plugin component to load its
             * UI content.  The parent container should also be sure that previous content in the block is removed first.
             *
             * @param parent {jsx3.app.Model} a model object to load the content into.  Plugin components are advised to
             *               use the <code>{ux.megatron.Main.loadUIResource}</code> function to do the content loading.
             */
            plugin.prototype.loadComponent = jsx3.lang.Method.newAbstract("parent");

            /**
             * Abstract method to be implemented by all plugin components.<br /><br />
             * Returns an instance of the plugin component.  The plugin component may use the <code>id</code> to identify
             * unique instances (caching them if necessary), or may choose to be a singleton by returning the same instance
             * for every call.<br /><br />
             * Parent plugin containers should call this on their child plugin components to get the specific instance to work
             * (rather than using the constructor).
             *
             * @param id {String} an identifier used for identifying unique instances of the plugin component
             */
            plugin.getInstance = jsx3.lang.Method.newAbstract("id");

            if(!plugin.prototype.allowComponentUnload) {
                plugin.prototype.allowComponentUnload = function(target, fctnYes, fctnNo, args) {
                    if(this.isPluginContainer()) {
                        this.allowComponentUnload = ux.megatron.plugin.PluginContainerInterface.prototype.allowComponentUnload;
                        this.allowComponentUnload(target, fctnYes, fctnNo, args);
                    }
                    else {
                        if(!this.isInEditMode()) {
                            fctnYes.call(target, args);
                        }
                        else {
                            var me = this;
                            ux.megatron.Dialog.confirm(this.getConfirmTitle(), this.getConfirmText(),
                                    function(dialog) {
                                        dialog.doClose();
                                        me.doCancelEdits();
                                        fctnYes.call(target, args);
                                    },
                                    function(dialog) {
                                        dialog.doClose();
                                        if(fctnNo) {
                                            fctnNo.call(target, args);
                                        }
                                    },
                                    this.getConfirmYesButtonText(), this.getConfirmNoButtonText(), this.getDefaultConfirmButton());
                        }
                    }
                };
            }

            if(!plugin.prototype.onAfterComponentUnloaded) {
                plugin.prototype.onAfterComponentUnloaded = function() {
                    if(this.isPluginContainer()) {
                        this.onAfterComponentUnloaded = ux.megatron.plugin.PluginContainerInterface.prototype.onAfterComponentUnloaded;
                        return this.onAfterComponentUnloaded();
                    }
                    else {
                        ux.megatron.Main.logException(new jsx3.Exception("WARNING!!!!   The plugin " + this.getClass().getName() + " does not override the onAfterComponentUnloaded function to perform cleanup after it's main UI component is unloaded."));
                    }
                }
            }

            if(!plugin.prototype.isInEditMode) {
                plugin.prototype.isInEditMode = function() {
                    if(this.isPluginContainer()) {
                        this.isInEditMode = ux.megatron.plugin.PluginContainerInterface.prototype.isInEditMode;
                        return this.isInEditMode();
                    }
                    else {
                        return this.isEditMode;
                    }
                }
            }

            plugin.prototype.getConfirmTitle = function() {
                return ux.megatron.Main.getServer().getDynamicProperty("@addin@PluginContainer Default Confirm Discard Title");
            }

            plugin.prototype.getConfirmText = function() {
                return ux.megatron.Main.getServer().getDynamicProperty("@addin@PluginContainer Default Confirm Discard Text");
            }

            plugin.prototype.getConfirmYesButtonText = function() {
                return ux.megatron.Main.getServer().getDynamicProperty("@addin@Btn Yes");
            }

            plugin.prototype.getConfirmNoButtonText = function() {
                return ux.megatron.Main.getServer().getDynamicProperty("@addin@Btn No");
            }

            plugin.prototype.getDefaultConfirmButton = function() {
                return 2;
            }

            if(!plugin.prototype.unload) {
                plugin.prototype.unload = function() {
                    if(this.isPluginContainer()) {
                        this.unload = ux.megatron.plugin.PluginContainerInterface.prototype.unload;
                        return this.unload();
                    }
                    else {
                        try {
                            if(this.isInEditMode()) {
                                this.endEditMode();
                            }
                            return this.onAfterComponentUnloaded();
                        }
                        catch(ex) {
                            // occasionally, harmless errors occur here when the ui is gone
                        }
                    }
                }
            }

            plugin.prototype.beginEditMode = function() {
                if(this.callbackTarget && this.beginEditCallback && this.endEditCallback) {
                    this.isEditMode = true;
                    try {
                        var me = this;
                        this.beginEditCallback.call(this.callbackTarget, me);
                    }
                    catch(ex) {
                        //                ux.megatron.Main.logException(ex);
                    }
                }
            }

            plugin.prototype.endEditMode = function() {
                if(this.callbackTarget && this.beginEditCallback && this.endEditCallback) {
                    this.isEditMode = false;
                    try {
                        var me = this;
                        this.endEditCallback.call(this.callbackTarget, me);
                    }
                    catch(ex) {
                        //                    ux.megatron.Main.logException(ex);
                    }
                }
            }

            plugin.prototype.isPluginContainer = function() {
                var isContainer = false;
                var intList = this.getClass().getInterfaces();
                for(var i = 0; i < intList.length; i++) {
                    if(intList[i].getName() == "ux.megatron.plugin.PluginContainerInterface") {
                        isContainer = true;
                        break;
                    }
                }
                return isContainer;
            }

            plugin.prototype.doCancelEdits = function() {
            }
        }
        );